home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2001 December / pcwk12201b.iso / Wersje pelne i specjalne / Winamp 2.77 i 3.0beta / wasabi-sdk_beta1.exe / studio / common / scrollbar.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  14.2 KB  |  644 lines

  1. /*
  2.  
  3.   Nullsoft WASABI Source File License
  4.  
  5.   Copyright 1999-2001 Nullsoft, Inc.
  6.  
  7.     This software is provided 'as-is', without any express or implied
  8.     warranty.  In no event will the authors be held liable for any damages
  9.     arising from the use of this software.
  10.  
  11.     Permission is granted to anyone to use this software for any purpose,
  12.     including commercial applications, and to alter it and redistribute it
  13.     freely, subject to the following restrictions:
  14.  
  15.     1. The origin of this software must not be misrepresented; you must not
  16.        claim that you wrote the original software. If you use this software
  17.        in a product, an acknowledgment in the product documentation would be
  18.        appreciated but is not required.
  19.     2. Altered source versions must be plainly marked as such, and must not be
  20.        misrepresented as being the original software.
  21.     3. This notice may not be removed or altered from any source distribution.
  22.  
  23.  
  24.   Brennan Underwood
  25.   brennan@nullsoft.com
  26.  
  27. */
  28.  
  29. #include <windows.h>
  30. #include "scrollbar.h"
  31. #include "canvas.h"
  32.  
  33. #define TIMER_ID  9871
  34. #define TIMER_ID2 9872
  35.  
  36. #define FIRST_DELAY 350
  37. #define NEXT_DELAY  75
  38.  
  39. ScrollBar::ScrollBar() {
  40.   leftrgn = NULL;
  41.   rightrgn = NULL;
  42.   buttonrgn = NULL;
  43.  
  44.   position = 0;
  45.   moving = 0;
  46.   lefting = 0;
  47.   righting = 0;
  48.   clicked = 0;
  49.   height = DEFAULT_HEIGHT;
  50.   buttonx = 0;
  51.  
  52.   shiftleft = 0;
  53.   shiftright = 0;
  54.  
  55.   curmouseposition = POS_NONE;
  56.   clickmouseposition = POS_NONE;
  57.   pageing = 0;
  58.   timer = 0;
  59.   npages = 100;
  60.   pageway = PAGE_NONE;
  61.   updown = 256;
  62.   insetpos = 0;
  63.  
  64.   vertical = 0;
  65. }
  66.  
  67. ScrollBar::~ScrollBar() {
  68.   deleteResources();
  69. }
  70.  
  71. void ScrollBar::deleteResources() {
  72.   if (leftrgn) delete leftrgn; leftrgn = NULL;
  73.   if (buttonrgn) delete buttonrgn; buttonrgn = NULL;
  74.   if (rightrgn) delete rightrgn; rightrgn = NULL;
  75. }
  76.  
  77. // this one is inherited
  78. void ScrollBar::freeResources() {
  79.   SCROLLBAR_PARENT::freeResources();
  80.   deleteResources();
  81. }
  82.  
  83. void ScrollBar::reloadResources() {
  84.   SCROLLBAR_PARENT::reloadResources();
  85.   loadBmps();
  86. }
  87.  
  88.  
  89. int ScrollBar::onMouseMove (int x, int y) {
  90.  
  91.   SCROLLBAR_PARENT::onMouseMove(x, y);
  92.   lastx = x;
  93.   lasty = y;
  94.  
  95.   if (clicked && clickmouseposition == POS_BUTTON) {
  96.  
  97.     POINT pt={x,y};
  98.     int x;
  99.     if (!vertical) 
  100.       x = pt.x - clickpos.x;
  101.     else
  102.       x = pt.y - clickpos.y;
  103.  
  104.     RECT r;
  105.     getClientRect(&r);
  106.     int maxwidth;
  107.     if (!vertical)
  108.       maxwidth = (r.right-r.left)-(shiftright+shiftleft+bmpbutton.getWidth())+1;
  109.     else
  110.       maxwidth = (r.bottom-r.top)-(shiftright+shiftleft+bmpbutton.getHeight())+1;
  111.     buttonx = min(max(clickbuttonx + x, 0), maxwidth);
  112.     calcPosition();
  113.     invalidate();
  114.  
  115.   } else {
  116.  
  117.     int oldposition = curmouseposition;
  118.     curmouseposition = getMousePosition();
  119.     if (oldposition != curmouseposition) invalidate();
  120.  
  121.     if (curmouseposition != POS_NONE && !getCapture())
  122.       beginCapture();
  123.  
  124.     if (curmouseposition == POS_NONE && getCapture() && !clicked && !pageing)
  125.       endCapture();
  126.   }
  127.  
  128.  
  129.   return 1;
  130. }
  131.  
  132. int ScrollBar::getWidth() {
  133.   if (!bmpbutton) return 0;
  134.   if (!vertical)
  135.     return bmpbutton.getHeight();
  136.   else
  137.     return bmpbutton.getWidth();
  138.   return 0;
  139. }
  140.  
  141. int ScrollBar::getMousePosition() {
  142.   int v = POS_NONE;
  143.  
  144.   POINT pt={lastx, lasty};
  145.  
  146.   RECT c;
  147.   getClientRect(&c);
  148.   pt.x -= c.left;
  149.   pt.y -= c.top;
  150.  
  151.   Region *l, *b, *r;
  152.   l = leftrgn->clone();
  153.   b = buttonrgn->clone();
  154.   if (!vertical)
  155.     b->offset(buttonx+shiftleft, 0);
  156.   else
  157.     b->offset(0, buttonx+shiftleft);
  158.   r = rightrgn->clone();
  159.   if (!vertical)
  160.     r->offset(c.right-c.left-bmpleft.getWidth(), 0);
  161.   else
  162.     r->offset(0, c.bottom-c.top-bmpleft.getHeight());
  163.  
  164.   if (b->ptInRegion(&pt))
  165.     v = POS_BUTTON;
  166.   if (l->ptInRegion(&pt))
  167.     v = POS_LEFT;
  168.   if (r->ptInRegion(&pt))
  169.     v = POS_RIGHT;
  170.  
  171.   delete l;
  172.   delete b;
  173.   delete r;
  174.  
  175.   return v;
  176. }
  177.  
  178. int ScrollBar::onLeftButtonDown(int x, int y) {
  179.   clickmouseposition = getMousePosition();
  180.   if (!pageing && clickmouseposition != POS_NONE) {
  181.     clicked = 1;
  182.     if (clickmouseposition == POS_LEFT || clickmouseposition == POS_RIGHT)
  183.       handleUpDown();
  184.     if (clickmouseposition) {
  185.       clickpos.x = lastx;
  186.       clickpos.y = lasty;
  187.       clickbuttonx = buttonx;
  188.     }
  189.   } else {
  190.     clicked = 0;
  191.     pageing = 1;
  192.     handlePageUpDown();
  193.   }
  194.   invalidate();
  195.   return 1;
  196. }
  197.  
  198. void ScrollBar::handleUpDown() {
  199.   setTimer(TIMER_ID2, FIRST_DELAY);
  200.   timer2 = 1;
  201.   firstdelay = 1;
  202.  
  203.   checkUpDown();
  204. }
  205.  
  206. int ScrollBar::checkUpDown() {
  207.   if (!clicked) {
  208.     if (timer2) {
  209.       killTimer(TIMER_ID2);
  210.       timer2 = 0;
  211.       return 1;
  212.     }
  213.   }
  214.  
  215.   if (getMousePosition() == clickmouseposition)
  216.     upDown(clickmouseposition);
  217.  
  218.   return 1;
  219.  
  220. }
  221.  
  222. void ScrollBar::handlePageUpDown() {
  223.  
  224.   setTimer(TIMER_ID, FIRST_DELAY);
  225.   timer = 1;
  226.   firstdelay = 1;
  227.  
  228.   checkPageUpDown();
  229. }
  230.  
  231. int ScrollBar::checkPageUpDown() {
  232.  
  233.   if (!pageing) {
  234.     if (timer) {
  235.       killTimer(TIMER_ID);
  236.       timer = 0;
  237.       pageway = PAGE_NONE;
  238.       return 1;
  239.     }
  240.   }
  241.  
  242.   POINT pt={lastx,lasty};
  243.   RECT c;
  244.   getClientRect(&c);
  245.   pt.x -= c.left;
  246.   pt.y -= c.top;
  247.   
  248.   if (!vertical) {
  249.     int middlebutton = shiftleft + buttonx + bmpbutton.getWidth()/2;
  250.     Region *r = buttonrgn->clone();
  251.     r->offset(buttonx+shiftleft, 0);
  252.     if (pt.x > middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_DOWN)
  253.       pageUp();
  254.     if (pt.x < middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_UP)
  255.       pageDown();
  256.     delete r;
  257.   } else {
  258.     int middlebutton = shiftleft + buttonx + bmpbutton.getHeight()/2;
  259.     Region *r = buttonrgn->clone();
  260.     r->offset(0, buttonx+shiftleft);
  261.     if (pt.y > middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_DOWN)
  262.       pageUp();
  263.     if (pt.y < middlebutton && !r->ptInRegion(&pt) && pageway != PAGE_UP)
  264.       pageDown();
  265.     delete r;
  266.   }
  267.   return 1;
  268.  
  269. }
  270.  
  271. int ScrollBar::onLeftButtonUp(int x, int y) {
  272.   clicked = 0;
  273.   clickmouseposition = POS_NONE;
  274.   curmouseposition = POS_NONE;
  275.   onMouseMove(x,y);
  276.   if (pageing) {
  277.     pageing = 0;
  278.     checkPageUpDown();
  279.   }
  280.   onSetFinalPosition();
  281.   invalidate();
  282.   return 1;
  283. }
  284.  
  285. int ScrollBar::onRightButtonDown(int x, int y) {
  286.   return 1;
  287. }
  288.  
  289. int ScrollBar::onRightButtonUp(int x, int y) {
  290.   return 1;
  291. }
  292.  
  293. int ScrollBar::onMouseWheelUp(int clicked, int lines) {
  294.   return 1;
  295. }
  296.  
  297. int ScrollBar::onMouseWheelDown(int clicked, int lines) {
  298.   return 1;
  299. }
  300.  
  301. int ScrollBar::onPaint(Canvas *canvas) {
  302.   AutoSkinBitmap &thisleft = curmouseposition == POS_LEFT ? (clicked ? bmplpressed : bmplhilite) : bmpleft;
  303.   AutoSkinBitmap &thisbutton = curmouseposition == POS_BUTTON ? (clicked ? bmpbpressed : bmpbhilite) : bmpbutton;
  304.   AutoSkinBitmap &thisright = curmouseposition == POS_RIGHT ? (clicked ? bmprpressed : bmprhilite) : bmpright;
  305.  
  306.   if (curmouseposition != clickmouseposition && clicked) {
  307.     thisleft = bmpleft;
  308.     thisbutton = bmpbutton;
  309.     thisright = bmpright;
  310.   }
  311.  
  312.   RECT r;
  313.   PaintBltCanvas paintcanvas;
  314.  
  315.   if (canvas == NULL) {
  316.     if (!paintcanvas.beginPaint(this)) return 0;
  317.     canvas = &paintcanvas;
  318.   }
  319.   SCROLLBAR_PARENT::onPaint(canvas);
  320.  
  321.   getClientRect(&r);
  322.  
  323.   renderBaseTexture(canvas, r);
  324.  
  325.   if (!vertical) {
  326.     RECT c;
  327.  
  328.     c.left = r.left + buttonx+shiftleft;
  329.     c.top = r.top + 0;
  330.     c.right = r.left + buttonx+thisbutton.getWidth()+shiftleft;
  331.     c.bottom = r.top + getWidth();
  332.  
  333.     thisbutton.stretchToRectAlpha(canvas, &c);
  334.  
  335.     c.left = r.left;
  336.     c.top = r.top;
  337.     c.right = r.left + thisleft.getWidth();
  338.     c.bottom = r.top + getWidth();
  339.  
  340.     thisleft.stretchToRectAlpha(canvas, &c);
  341.  
  342.     c.left = r.right-thisright.getWidth();
  343.     c.top = r.top;
  344.     c.right = r.right;
  345.     c.bottom = r.top+getWidth();
  346.  
  347.     thisright.stretchToRectAlpha(canvas, &c);
  348.   } else {
  349.     RECT c;
  350.     c.left = r.right - thisleft.getWidth();
  351.     c.top = r.top+buttonx + shiftleft;
  352.     c.right = r.right;
  353.     c.bottom = r.top+buttonx+thisbutton.getHeight() + shiftleft;
  354.  
  355.     thisbutton.stretchToRectAlpha(canvas, &c);
  356.  
  357.     c.left = r.right - thisleft.getWidth();
  358.     c.top = r.top;
  359.     c.right = r.right;
  360.     c.bottom = r.top+thisleft.getHeight();
  361.  
  362.     thisleft.stretchToRectAlpha(canvas, &c);
  363.  
  364.     c.left = r.right-thisright.getWidth();
  365.     c.top = r.bottom-thisright.getHeight();
  366.     c.right = r.right;
  367.     c.bottom = r.bottom;
  368.  
  369.     thisright.stretchToRectAlpha(canvas, &c);
  370.   }
  371.  
  372.   return 1;
  373. }
  374.  
  375. int ScrollBar::getHeight() {
  376.   return height;
  377. }
  378.  
  379. void ScrollBar::setHeight(int newheight) {
  380.   height = newheight;
  381. }
  382.  
  383. int ScrollBar::onResize() {
  384.   calcXPosition();
  385.   invalidate();
  386.   return 1;
  387. }
  388.  
  389. int ScrollBar::onInit() {
  390.   SCROLLBAR_PARENT::onInit();
  391.   return 1;
  392. }
  393.  
  394. void ScrollBar::setBitmaps(char *left, char *lpressed, char *lhilite,
  395.                   char *right, char *rpressed, char *rhilite, 
  396.                   char *button, char *bpressed, char *bhilite) {
  397.  
  398.   deleteResources();
  399.  
  400.   bmpleft = left;
  401.   bmplpressed = lpressed;
  402.   bmplhilite = lhilite;
  403.   bmpright = right;
  404.   bmprpressed = rpressed;
  405.   bmprhilite = rhilite;
  406.   bmpbutton = button;
  407.   bmpbpressed = bpressed;
  408.   bmpbhilite = bhilite;
  409.  
  410.   loadBmps();
  411. }
  412.  
  413. void ScrollBar::loadBmps() {
  414.  
  415.   if (bmpleft) leftrgn = new Region(bmpleft);
  416.   if (bmpbutton) buttonrgn = new Region(bmpbutton);
  417.   if (bmpright) rightrgn = new Region(bmpright);
  418.  
  419.   calcOverlapping();
  420.   calcXPosition();
  421. }
  422.  
  423. void ScrollBar::setPosition(int pos) {
  424.   setPrivatePosition(pos, FALSE);
  425. }
  426.  
  427. void ScrollBar::setPrivatePosition(int pos, BOOL signal, BOOL smooth) {
  428.   if (insetpos) return; // helps stupid people (like me)
  429.   insetpos = 1;
  430.   position = min(SCROLLBAR_FULL, pos);
  431.   position = max(0, position);
  432.   calcXPosition();
  433.   if (signal) onSetPosition(smooth);
  434.   if (isInited() && isVisible())
  435.   invalidate();
  436.   insetpos = 0;
  437. }
  438.  
  439. int ScrollBar::getPosition() {
  440.   return position;
  441. }
  442.  
  443. int ScrollBar::onSetPosition(BOOL smooth) {
  444.   notifyParent(UMSG_SCROLLBAR_SETPOSITION, smooth);
  445.   return 1;
  446. }
  447.  
  448. int ScrollBar::onSetFinalPosition() {
  449.   notifyParent(UMSG_SCROLLBAR_SETFINALPOSITION);
  450.   return 1;
  451. }
  452.  
  453. void ScrollBar::calcOverlapping() {
  454.  
  455.   if (!vertical) {
  456.  
  457.     shiftleft = bmpleft.getWidth();
  458.     if (leftrgn && buttonrgn) {
  459.       for (int i=shiftleft;i>=0;i--) {
  460.         Region *reg = buttonrgn->clone();
  461.         reg->offset(i, 0);
  462.         if (leftrgn->intersects(reg)) {
  463.           delete reg;
  464.           i++;
  465.           break;
  466.         }
  467.         delete reg;
  468.       }
  469.       if (i >= 0)
  470.         shiftleft = i;
  471.     }
  472.  
  473.     shiftright = bmpright.getWidth();
  474.     if (rightrgn && buttonrgn) {
  475.       for (int i=0;i>=-shiftright;i--) {
  476.         Region *reg = rightrgn->clone();
  477.         reg->offset(i+bmpbutton.getWidth(), 0);
  478.         if (reg->intersects(buttonrgn)) {
  479.           delete reg;
  480.           i++;
  481.           break;
  482.         }
  483.         delete reg;
  484.       }
  485.       if (i >= -shiftright)
  486.         shiftright += i;
  487.     }
  488.  
  489.   } else {
  490.  
  491.     shiftleft = bmpleft.getHeight();
  492.     if (leftrgn && buttonrgn) {
  493.       for (int i=shiftleft;i>=0;i--) {
  494.         Region *reg = buttonrgn->clone();
  495.         reg->offset(0, i);
  496.         if (leftrgn->intersects(reg)) {
  497.           delete reg;
  498.           i++;
  499.           break;
  500.         }
  501.         delete reg;
  502.       }
  503.       if (i >= 0)
  504.         shiftleft = i;
  505.     }
  506.  
  507.     shiftright = bmpright.getHeight();
  508.     if (rightrgn && buttonrgn) {
  509.       for (int i=0;i>=-shiftright;i--) {
  510.         Region *reg = rightrgn->clone();
  511.         reg->offset(0, i+bmpbutton.getHeight());
  512.         if (reg->intersects(buttonrgn)) {
  513.           delete reg;
  514.           i++;
  515.           break;
  516.         }
  517.         delete reg;
  518.       }
  519.       if (i >= -shiftright)
  520.         shiftright += i;
  521.     }
  522.  
  523.   }
  524.  
  525. }
  526.  
  527. void ScrollBar::calcXPosition() {
  528.  
  529.   if (!isInited()) return;
  530.  
  531.   RECT r;
  532.   getClientRect(&r);
  533.  
  534.   int maxwidth;
  535.  
  536.   if (!vertical)
  537.     maxwidth = (r.right-r.left)-(bmpbutton.getWidth()+shiftleft+shiftright)+1;
  538.   else
  539.     maxwidth = (r.bottom-r.top)-(bmpbutton.getHeight()+shiftleft+shiftright)+1;
  540.   int oldx = buttonx;
  541.   buttonx = (int)(((float)getPosition() / SCROLLBAR_FULL) * maxwidth);
  542.   if (buttonx != oldx)
  543.     invalidate();
  544. }
  545.  
  546. void ScrollBar::calcPosition() {
  547.  
  548.   if (!isInited()) return;
  549.  
  550.   RECT r;
  551.   getClientRect(&r);
  552.  
  553.   int maxwidth;
  554.  
  555.   if (!vertical)
  556.     maxwidth = r.right-r.left-(bmpbutton.getWidth()+shiftleft+shiftright)+1;
  557.   else
  558.     maxwidth = r.bottom-r.top-(bmpbutton.getHeight()+shiftleft+shiftright)+1;
  559.   setPrivatePosition((int)((float)buttonx / maxwidth * SCROLLBAR_FULL));
  560.   //invalidate();
  561. }
  562.  
  563. void ScrollBar::timerCallback(int id) {
  564.   switch (id) {
  565.     case TIMER_ID:
  566.       if (firstdelay) {
  567.         killTimer(TIMER_ID);
  568.         setTimer(TIMER_ID, NEXT_DELAY);
  569.         timer = 1;
  570.         firstdelay = 0;
  571.       }
  572.       checkPageUpDown();
  573.       break;
  574.     case TIMER_ID2:
  575.       if (firstdelay) {
  576.         killTimer(TIMER_ID2);
  577.         setTimer(TIMER_ID2, NEXT_DELAY);
  578.         timer2 = 1;
  579.         firstdelay = 0;
  580.       }
  581.       checkUpDown();
  582.       break;
  583.     default:
  584.       SCROLLBAR_PARENT::timerCallback(id);
  585.   }
  586. }
  587.  
  588. int ScrollBar::pageUp() { 
  589.  
  590.   pageway = PAGE_UP;
  591.  
  592.   setPrivatePosition((int)max(0, (float)getPosition() + (float)SCROLLBAR_FULL / (npages-1)), TRUE, TRUE);
  593.  
  594.   return 1; 
  595. };
  596.  
  597. int ScrollBar::pageDown() { 
  598.  
  599.   pageway = PAGE_DOWN;
  600.  
  601.   setPrivatePosition((int)min(SCROLLBAR_FULL, (float)getPosition() - (float)SCROLLBAR_FULL / (npages-1)), TRUE, TRUE);
  602.  
  603.   return 1; 
  604. };
  605.  
  606. void ScrollBar::setNPages(int n) {
  607.   //ASSERT(n >= 2);
  608.   if (n < 2) n = 2;
  609.   npages = n;
  610. }
  611.  
  612. void ScrollBar::gotoPage(int page) {
  613.  
  614.   page = min(page, npages-1);
  615.   page = max(page, 0);
  616.  
  617.   setPrivatePosition((int)((float)SCROLLBAR_FULL / (npages-1) * page), TRUE, FALSE);
  618.  
  619. }
  620.  
  621. void ScrollBar::setUpDownValue(int newupdown) {
  622.   updown = newupdown;
  623. }
  624.  
  625. int ScrollBar::upDown(int which) {
  626.   switch (which) {
  627.     case POS_LEFT:
  628.       setPrivatePosition(getPosition()-updown);
  629.       break;
  630.     case POS_RIGHT:
  631.       setPrivatePosition(getPosition()+updown);
  632.       break;
  633.   }
  634.   return 1;
  635. }
  636.  
  637. void ScrollBar::setVertical(int isvertical) {
  638.   vertical = isvertical;
  639.   calcOverlapping();
  640.   if (isInited())
  641.     invalidate();
  642. }
  643.  
  644.